#_*_ coding:utf8 _*_
from DEV_SNMP import *      # 导入编写在另一个文件里的SNMP操作函数
import sys                  # 本例中用于获取函数名写入日志文件
import logging              # 日志模块
Log = logging.getLogger("__name__")
## 如果日志实例不存在，就使用本程序日志模块
if not logging.FileHandler:
    formatter = logging.Formatter('%(asctime)s %(levelname)-8s : %(message)s')  # 指定logger输出格式
    file_handler = logging.FileHandler("DEF_SNMP_eNSP_Switch_S5700.log")        # 日志文件路径
    file_handler.setFormatter(formatter)                                        # 可以通过setFormatter指定输出格式
    Log.addHandler(file_handler)
    Log.setLevel(logging.DEBUG)


## 函数调用关系
'''
DEF_SNMP_eNSP_Switch_S5700.py
    from DEV_SNMP import *      # 需要导入编写DEV_SNMP.py文件里的SNMP操作函数
    import sys                  # 本文件中只用于获取函数名方便生成日志内容
    import logging              # 日志模块
    SNMP_MAC_2_mac(SNMP_MAC)                                               ## SNMP获取的MAC地址是 '00 00 00 00 00 00' 形式，需要转成 '0000-0000-0000' 形式
    SNMP_L_Bind_IP_STR(SNMP_PWD, SNMP_HOST)                                ## 获取静态绑定IP列表
    SNMP_L_Bind_MAC_STR(SNMP_PWD, SNMP_HOST)                               ## 获取静态绑定MAC列表
    SNMP_L_IF_IP_STR(SNMP_PWD, SNMP_HOST)                                  ## 获取设备接口IP列表（VLAN接口、物理端口、特殊接口）
    SNMP_L_IF_MASK_STR(SNMP_PWD, SNMP_HOST)                                ## 获取设备接口IP的掩码列表（VLAN接口、物理端口、特殊接口）
    SNMP_L_IF_INDEX_STR(SNMP_PWD, SNMP_HOST)                               ## 获取设备接口编号（VLAN接口、物理端口、特殊接口）
    SNMP_D_IF_DESCR(SNMP_PWD, SNMP_HOST)                                   ## 获取设备接口名称字典（VLAN接口、物理端口、特殊接口）## {'1':InLoopBack0, '2':'NULL0', '3':'Console9/0/0', '4':'MEth0/0/1', '5':'Vlanif1', '6':'GigabitEthernet0/0/1'}
    SNMP_生成以IP为键以MAC地址列表为值的字典(SNMP_PWD, SNMP_HOST)          ## 以IP为键以MAC地址列表为值的字典 {IP_STR:[MAC_STR, MAC_STR]}
        SNMP_L_Bind_IP_STR(SNMP_PWD, SNMP_HOST)
        SNMP_L_Bind_MAC_STR(SNMP_PWD, SNMP_HOST)
            SNMP_MAC_2_mac(SNMP_MAC)
    SNMP_生成以VLAN为键以VLAN_IP_MASK列表为值的字典(SNMP_PWD, SNMP_HOST)   ## D_VLAN_NET {VLAN_STR:[IP_STR/MASK_STR]}
        SNMP_L_IF_IP_STR(SNMP_PWD, SNMP_HOST)   
        SNMP_L_IF_MASK_STR(SNMP_PWD, SNMP_HOST) 
        SNMP_L_IF_INDEX_STR(SNMP_PWD, SNMP_HOST)
        SNMP_D_IF_DESCR(SNMP_PWD, SNMP_HOST)    
'''


## 全局变量 交换机 S5700 要用到的 OID
OID_BIND_IP = '1.3.6.1.4.1.2011.5.25.112.1.14.1.12'         # 静态绑定IP列表
OID_BIND_MAC = '1.3.6.1.4.1.2011.5.25.112.1.14.1.11'        # 静态绑定MAC列表
OID_IF_IP_STR = '1.3.6.1.4.1.2011.5.25.41.1.2.1.1.1'        # 设备接口IP列表（VLAN接口、物理端口、特殊接口）
OID_IF_MASK_STR = '1.3.6.1.4.1.2011.5.25.41.1.2.1.1.3'      # 设备接口IP的掩码列表（VLAN接口、物理端口、特殊接口）
OID_IF_INDEX = '1.3.6.1.4.1.2011.5.25.41.1.2.1.1.2'         # 设备接口编号（VLAN接口、物理端口、特殊接口）
OID_IF_DESCR = 'IF-MIB::ifDescr'                            # 设备接口名称字典（VLAN接口、物理端口、特殊接口）


## SNMP获取的MAC地址是 '00 00 00 00 00 00' 形式，需要转成 '0000-0000-0000' 形式
def SNMP_MAC_2_mac(SNMP_MAC):
    MAC = SNMP_MAC.replace(' ', '')
    mac = MAC.lower()
    mac_new = mac[0:4] +'-'+ mac[4:8] +'-'+ mac[8:12]
    return(mac_new)


## 获取静态绑定IP列表
def SNMP_L_Bind_IP_STR(SNMP_PWD, SNMP_HOST):
    SNMP_OID = OID_BIND_IP
    (N, R) = SNMP_V2_R(SNMP_PWD, SNMP_HOST, SNMP_OID)
    if N == 0:
        if R.split(' = ')[-1] == 'No Such Object available on this agent at this OID':
            ERROR = '错误 OID ' + SNMP_OID
            return(1, ERROR)
        elif R.split(' = ')[-1] == 'No Such Instance currently exists at this OID':
            ## SNMP查询结果为空
            return(0, [])
        else:
            R_SP = R.split('\n')
            L_IP_STR = [i.split(': ')[-1] for i in R_SP]
            return(0, L_IP_STR)
    else:
        ERROR = 'SNMP命令执行失败：' + str(R)
        return(1, ERROR)


## 获取静态绑定MAC列表
def SNMP_L_Bind_MAC_STR(SNMP_PWD, SNMP_HOST):
    SNMP_OID = OID_BIND_MAC
    (N, R) = SNMP_V2_R(SNMP_PWD, SNMP_HOST, SNMP_OID)
    if N == 0:
        if R.split(' = ')[-1] == 'No Such Object available on this agent at this OID':
            ERROR = '错误 OID ' + SNMP_OID
            return(1, ERROR)
        elif R.split(' = ')[-1] == 'No Such Instance currently exists at this OID':
            ## SNMP查询结果为空
            return(0, [])
        else:
            R_SP = R.split('\n')
            L_MAC_STR = [SNMP_MAC_2_mac(i.split(': ')[-1]) for i in R_SP]
            return(0, L_MAC_STR)
    else:
        ERROR = 'SNMP命令执行失败：' + str(R)
        return(1, ERROR)


## 获取设备接口IP列表（VLAN接口、物理端口、特殊接口）
def SNMP_L_IF_IP_STR(SNMP_PWD, SNMP_HOST):
    SNMP_OID = OID_IF_IP_STR
    (N, R) = SNMP_V2_R(SNMP_PWD, SNMP_HOST, SNMP_OID)
    if N == 0:
        if R.split(' = ')[-1] == 'No Such Object available on this agent at this OID':
            ERROR = '错误 OID ' + SNMP_OID
            return(1, ERROR)
        elif R.split(' = ')[-1] == 'No Such Instance currently exists at this OID':
            ## SNMP查询结果为空
            return(0, [])
        else:
            R_SP = R.split('\n')                            ## 先用'\n'(换行符)分出每一条记录
            L_IP_STR = [i.split(': ')[-1] for i in R_SP]    ## 再用': '(冒号加一空)分段并提取需要的值(最后一段)
            return(0, L_IP_STR)
    else:
        ERROR = 'SNMP命令执行失败：' + str(R)
        return(1, ERROR)


## 获取设备接口IP的掩码列表（VLAN接口、物理端口、特殊接口）
def SNMP_L_IF_MASK_STR(SNMP_PWD, SNMP_HOST):
    SNMP_OID = OID_IF_MASK_STR
    (N, R) = SNMP_V2_R(SNMP_PWD, SNMP_HOST, SNMP_OID)
    if N == 0:
        if R.split(' = ')[-1] == 'No Such Object available on this agent at this OID':
            ERROR = '错误 OID ' + SNMP_OID
            return(1, ERROR)
        elif R.split(' = ')[-1] == 'No Such Instance currently exists at this OID':
            ## SNMP查询结果为空
            return(0, [])
        else:
            R_SP = R.split('\n')
            L_IF_MASK_STR = [i.split(': ')[-1] for i in R_SP]
            return(0, L_IF_MASK_STR)
    else:
        ERROR = 'SNMP命令执行失败：' + str(R)
        return(1, ERROR)


## 获取设备接口编号（VLAN接口、物理端口、特殊接口）
def SNMP_L_IF_INDEX_STR(SNMP_PWD, SNMP_HOST):
    SNMP_OID = OID_IF_INDEX
    (N, R) = SNMP_V2_R(SNMP_PWD, SNMP_HOST, SNMP_OID)
    if N == 0:
        if R.split(' = ')[-1] == 'No Such Object available on this agent at this OID':
            ERROR = '错误 OID ' + SNMP_OID
            return(1, ERROR)
        elif R.split(' = ')[-1] == 'No Such Instance currently exists at this OID':
            ## SNMP查询结果为空
            return(0, [])
        else:
            R_SP = R.split('\n')
            L_IF_VLAN_STR = [i.split(': ')[-1] for i in R_SP]
            return(0, L_IF_VLAN_STR)
    else:
        ERROR = 'SNMP命令执行失败：' + str(R)
        return(1, ERROR)


## 获取设备接口名称字典（VLAN接口、物理端口、特殊接口）
## {'1':InLoopBack0, '2':'NULL0', '3':'Console9/0/0', '4':'MEth0/0/1', '5':'Vlanif1', '6':'GigabitEthernet0/0/1'}
def SNMP_D_IF_DESCR(SNMP_PWD, SNMP_HOST):
    SNMP_OID = OID_IF_DESCR
    (N, R) = SNMP_V2_R(SNMP_PWD, SNMP_HOST, SNMP_OID)
    if N == 0:
        if R.split(' = ')[-1] == 'No Such Object available on this agent at this OID':
            ERROR = '错误 OID ' + SNMP_OID
            return(1, ERROR)
        elif R.split(' = ')[-1] == 'No Such Instance currently exists at this OID':
            ## SNMP查询结果为空
            return(0, {})
        else:
            D_IF_DESCR = {}
            R_SP = R.split('\n')                            ## 先用'\n'(换行符)分出每一条记录
            L_IF_DESCR = [i.split(': ')[-1] for i in R_SP]  ## 再用': '(冒号加一空)分段并提取需要的值(最后一段)
            for i in range(0, len(L_IF_DESCR)):
                D_IF_DESCR[str(i+1)] = L_IF_DESCR[i]
            return(0, D_IF_DESCR)
    else:
        ERROR = 'SNMP命令执行失败：' + str(R)
        return(1, ERROR)



## D_IP_MAC
## 以IP为键以MAC地址列表为值的字典
## {IP_STR:[MAC_STR, MAC_STR]}
## {'x.x.x.x':['xxxx-xxxx-xxxx', 'xxxx-xxxx-xxxx']}
## {'10.0.0.1':['0000-0000-000a', '0000-0000-000b']}
def SNMP_生成以IP为键以MAC地址列表为值的字典(SNMP_PWD, SNMP_HOST):
    (N_IP, R_IP) = SNMP_L_Bind_IP_STR(SNMP_PWD, SNMP_HOST)
    (N_MAC, R_MAC) = SNMP_L_Bind_MAC_STR(SNMP_PWD, SNMP_HOST)
    Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 SNMP_L_Bind_IP_STR 调用结果：' + str(N_IP) + str(R_IP))
    Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 SNMP_L_Bind_MAC_STR 调用结果：' + str(N_MAC) + str(R_MAC))
    if N_IP == 0:
        if N_MAC == 0:
            IP_List = R_IP
            MAC_List = R_MAC
            IP_List_Len = len(IP_List)
            MAC_List_Len = len(MAC_List)
            if IP_List_Len == MAC_List_Len:
                D_IP_MAC = {}
                for i in range(0, IP_List_Len):
                    IP = IP_List[i]
                    MAC = MAC_List[i]
                    if IP not in D_IP_MAC:
                        D_IP_MAC[IP] = [MAC]
                    else:
                        D_IP_MAC[IP].append(MAC)
                return(0, D_IP_MAC)
            else:
                E = '绑定记录IP和MAC不能一一对应，len(IP_List) != len(MAC_List)'
                return(1, E)
        else:
            E = '获取IP成功，获取MAC失败：' + R_MAC
            return(1, E)
    else:
        if N_MAC == 0:
            E = '获取MAC成功，获取IP失败：' + R_IP
            return(1, E)
        else:
            E = '获取IP失败：' + R_IP + ' 获取MAC失败：' + R_MAC
            return(1, E)



## D_VLAN_NET
## {VLAN_STR:[IP_STR/MASK_STR]}
## {'VlanifN':['x.x.x.x/x.x.x.x', 'x.x.x.x/x.x.x.x']}
def SNMP_生成以VLAN为键以VLAN_IP_MASK列表为值的字典(SNMP_PWD, SNMP_HOST):
    D_VLAN_NET = {}
    (N_IP, R_IP) = SNMP_L_IF_IP_STR(SNMP_PWD, SNMP_HOST)
    (N_MASK, R_MASK) = SNMP_L_IF_MASK_STR(SNMP_PWD, SNMP_HOST)
    (N_INDEX, R_INDEX) = SNMP_L_IF_INDEX_STR(SNMP_PWD, SNMP_HOST)
    (N_DESCR, R_DESCR) = SNMP_D_IF_DESCR(SNMP_PWD, SNMP_HOST)
    Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 SNMP_L_IF_IP_STR 调用结果：' + str(N_IP) + str(R_IP))
    Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 SNMP_L_IF_MASK_STR 调用结果：' + str(N_MASK) + str(R_MASK))
    Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 SNMP_L_IF_INDEX_STR 调用结果：' + str(N_INDEX) + str(R_INDEX))
    Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 SNMP_D_IF_DESCR 调用结果：' + str(N_DESCR) + str(R_DESCR))
    if N_IP == N_MASK == N_INDEX == N_DESCR == 0:
        if len(R_IP) == len(R_MASK) == len(R_INDEX):
            for i in range(0, len(R_IP)):
                VLAN = R_INDEX[i]
                IP = R_IP[i]
                MASK = R_MASK[i]
                if VLAN in R_DESCR:
                    KEY = R_DESCR[VLAN]
                    VALUE = IP + '/' + MASK
                    if KEY not in D_VLAN_NET:
                        D_VLAN_NET[KEY] = [VALUE]
                    else:
                        D_VLAN_NET[KEY].append(VALUE)
                else:
                    ERROR = 'VLAN ' + VLAN + ' 在设备中没有找到'
                    return(1, ERROR)
            return(0, D_VLAN_NET)
        else:
            ERROR = 'IP MASK VLAN 数量不一致'
            return(1, ERROR)
    else:
        ERROR = '有错误 '
        if N_IP != 0:
            ERROR += R_IP
        if N_MASK != 0:
            ERROR += R_MASK
        if N_INDEX != 0:
            ERROR += R_INDEX
        if N_DESCR != 0:
            ERROR += R_DESCR
        return(1, ERROR)





